using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.WebControls;
using System.Xml;
using System.Xml.Serialization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

namespace ListActivityWebPart
{
    [Guid("4d1125a5-aa9f-49e9-a6cd-b26da8cfaf4a")]
    public class ListActivityWebPart : System.Web.UI.WebControls.WebParts.WebPart
    {
        private string _xamlUrl = "/_layouts/ListActivity/DisplayListActivity.xaml";
        private string _agJsUrl = "/_layouts/silverlight/silverlight.js";
        private string _agControlID = "";
        private string _bar1Color = "Green";
        private string _bar2Color = "Orange";
        private bool _display0ActivityLists = true;
        private bool _openListInNewWindow = true;
        private string _siteTitle = "";
        private string _siteDescription = "";
        private string _webUrl = "";
        private bool _siteTitleInWPTitle = true;
        private bool _siteTitleInSilverlight = false;
        private string _listActivityXmlData;
        private string _optionsXmlData;

        private const string _agJsScriptKey = "agScript";
        private string _agControlScriptKey;

        [WebBrowsable(true), Personalizable(PersonalizationScope.User), WebDisplayName("SharePoint site Url"),
         Description("Enter relative site URL; leave blank for current site")]
        public string SharePointSiteUrl
        { get { return _webUrl; } set { _webUrl = value; } }

        [WebBrowsable(true), Personalizable(PersonalizationScope.User), WebDisplayName("Show site title in web part title"),
         Description("If selected, replaces Web Part title with site title")]
        public bool SiteTitleInWPtitle
        { get { return _siteTitleInWPTitle; } set { _siteTitleInWPTitle = value; } }

        [WebBrowsable(true), Personalizable(PersonalizationScope.User), WebDisplayName("Show site title in Silverlight control"),
         Description("If selected, shows site title in the Silveright control")]
        public bool SiteTitleInSilverlight
        { get { return _siteTitleInSilverlight; } set { _siteTitleInSilverlight = value; } }

        [WebBrowsable(true), Personalizable(PersonalizationScope.User), WebDisplayName("Open list in new browser")]
        public bool OpenListInNewWindow
        { get { return _openListInNewWindow; } set { _openListInNewWindow = value; } }

        [WebBrowsable(true), Personalizable(PersonalizationScope.User), WebDisplayName("Show lists with no activity")]
        public bool DisplayZeroActivityLists
        { get { return _display0ActivityLists; } set { _display0ActivityLists = value; } }

        [WebBrowsable(true), Personalizable(PersonalizationScope.User), WebDisplayName("Color for Yesterday's bar")]
        public string Bar1Color
        { get { return _bar1Color; } set { _bar1Color = value; } }

        [WebBrowsable(true), Personalizable(PersonalizationScope.User), WebDisplayName("Color for Today's bar")]
        public string Bar2Color
        { get { return _bar2Color; } set { _bar2Color = value; } }

        [WebBrowsable(true), Personalizable(PersonalizationScope.Shared), WebDisplayName("URL to List Activity XAML")]
        public string XamlUrl
        { get { return _xamlUrl; } set { _xamlUrl = value; } }

        [WebBrowsable(true), Personalizable(PersonalizationScope.Shared), WebDisplayName("URL to Silverlight.js")]
        public string SilverlightJsUrl
        { get { return _agJsUrl; } set { _agJsUrl = value; } }

        //[WebBrowsable(true), Personalizable(PersonalizationScope.Shared), WebDisplayName("Silverlight Control ID")]
        //public string SilverlightControlId
        //{ get { return _agControlID; } set { _agControlID = value; } }

        public ListActivityWebPart()
        {
            if (_agControlID == "")
            {
                _agControlID = Guid.NewGuid().ToString().Replace("-", "");
            }
            _agControlScriptKey = _agControlID + "_ScriptKey";

            this.ExportMode = WebPartExportMode.All;
            this.PreRender += new EventHandler(ListActivityWebPart_PreRender);
        }

        void ListActivityWebPart_PreRender(object sender, EventArgs e)
        {
            _listActivityXmlData = BuildListDataXMLString();
            _optionsXmlData = BuildOptionsXMLString();

            if (_siteTitleInWPTitle)
            {
                this.Title = _siteTitle;
            }

            if (!Page.ClientScript.IsClientScriptIncludeRegistered(_agJsScriptKey))
            {
                Page.ClientScript.RegisterClientScriptInclude(this.GetType(), _agJsScriptKey, _agJsUrl);
            }

            if (!Page.ClientScript.IsClientScriptBlockRegistered(_agControlScriptKey))
            {
                Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
                    _agControlScriptKey,
                    BuildSilverlightControlScript(_listActivityXmlData, _optionsXmlData));
            }

        }

        protected override void Render(HtmlTextWriter writer)
        {

            //writer.Write(BuildSilverlightControlScript(BuildListDataXMLString(), BuildOptionsXMLString()));
            writer.Write(BuildSilverlightControlDiv());
        }

        private string BuildSilverlightControlScript(string listXmlString, string optionsXmlString)
        {
            string silverlight = @"
<script>
function createSilverlight_" + _agControlID + @"()
{
	Silverlight.createObjectEx({
		source: '" + _xamlUrl + @"',
		parentElement: document.getElementById('Host_" + _agControlID + @"'),
		id: 'sc_" + _agControlID + @"',
		properties: {
			width: '100%',
			height: '100%',
			version: '1.1',
			enableHtmlAccess: 'true'
		},
		events: {onLoad:updateDisplay_" + _agControlID + @"}
	});
}
function updateDisplay_" + _agControlID + @"(plugin, userContext, sender)
{
    var control = document.getElementById('sc_" + _agControlID + @"');
    var listXmlString = '" + listXmlString + @"';

    if (control) {
        control.focus();
        control.Content.listActivity.SetOptions('" + optionsXmlString + @"');
        control.Content.listActivity.UpdateDisplay(listXmlString);
    }
}
</script>";

            return silverlight;
        }

        internal string BuildSilverlightControlDiv()
        {
            string controlDiv;
            controlDiv = @"<style type='text/css'>
    .HostStyle_" + _agControlID + @" { width: 100; height: 100; }
</style>
<div id='Host_" + _agControlID + @"' 
        class='HostStyle_" + _agControlID + @"' >
        <script type='text/javascript'>
            var context = '';
            createSilverlight_" + _agControlID + @"();
        </script>
    </div>";
            return controlDiv;
        }

        /// <summary>
        /// creates XML string representation of silverlight display options. It uses XmlTextWriter
        /// to create well-formed XML. I wonder, though, if it would be less resource-intensive to
        /// just use a string builder?
        /// </summary>
        /// <returns></returns>
        internal string BuildOptionsXMLString()
        {
            string optionsXmlString = "";
            using (System.IO.StringWriter w = new System.IO.StringWriter())
            {
                System.Xml.XmlTextWriter xr = new XmlTextWriter(w);
                xr.WriteStartElement("PropertyBag");
                xr.WriteStartElement("Property");//XamlUrl
                xr.WriteAttributeString("Name", "SharePointSiteUrl");
                xr.WriteAttributeString("Value", _webUrl);
                xr.WriteEndElement();//Property XamlUrl

                xr.WriteStartElement("Property");//XamlUrl
                xr.WriteAttributeString("Name", "XamlUrl");
                xr.WriteAttributeString("Value", _xamlUrl);
                xr.WriteEndElement();//Property XamlUrl

                xr.WriteStartElement("Property");//SilverlightJsUrl
                xr.WriteAttributeString("Name", "SilverlightJsUrl");
                xr.WriteAttributeString("Value", _agJsUrl);
                xr.WriteEndElement();//Property SilverlightJsUrl

                xr.WriteStartElement("Property");//SilverlightControlID
                xr.WriteAttributeString("Name", "SilverlightControlId");
                xr.WriteAttributeString("Value", "sc_" + _agControlID);
                xr.WriteEndElement();//Property SilverlightControlID

                xr.WriteStartElement("Property");//DisplayZeroActivityLists
                xr.WriteAttributeString("Name", "DisplayZeroActivityLists");
                xr.WriteAttributeString("Value", _display0ActivityLists.ToString());
                xr.WriteEndElement();//Property DisplayZeroActivityLists

                xr.WriteStartElement("Property");//OpenListInNewWindow
                xr.WriteAttributeString("Name", "OpenListInNewWindow");
                xr.WriteAttributeString("Value", _openListInNewWindow.ToString());
                xr.WriteEndElement();//Property OpenListInNewWindow

                xr.WriteStartElement("Property");//Bar1Color
                xr.WriteAttributeString("Name", "Bar1Color");
                xr.WriteAttributeString("Value", _bar1Color);
                xr.WriteEndElement();//Property Bar1Color

                xr.WriteStartElement("Property");//Bar2Color
                xr.WriteAttributeString("Name", "Bar2Color");
                xr.WriteAttributeString("Value", _bar2Color);
                xr.WriteEndElement();//Property Bar2Color

                xr.WriteStartElement("Property");//ShowSiteTitle
                xr.WriteAttributeString("Name", "ShowSiteTitle");
                xr.WriteAttributeString("Value", _siteTitleInSilverlight.ToString());
                xr.WriteEndElement();//Property ShowSiteTitle

                xr.WriteEndElement();//PropertyBag
                optionsXmlString = w.ToString();
            }
            return optionsXmlString;
        }

        //TODO: error handling!!!
        internal string BuildListDataXMLString()
        {

            SPWeb myweb;
            SPListItemCollection myitems;
            SimpleListCollection siteLists = new SimpleListCollection();
            string xmlString = "";

            //get reference to web which contains the lists
            try
            {

                if (_webUrl != "")
                {
                    myweb = SPContext.Current.Site.OpenWeb(_webUrl);
                }
                else
                {
                    myweb = SPContext.Current.Web;
                }

                SPListCollection mylists = myweb.Lists;

                _siteDescription = myweb.Description;
                _siteTitle = myweb.Title;

                siteLists.SiteDescription = _siteDescription;
                siteLists.SiteTitle = _siteTitle;
                siteLists.SiteUrl = _webUrl;

                foreach (SPList mylist in mylists)
                {
                    SimpleList siteList = new SimpleList();
                    SPQuery query = new SPQuery();
                    query.Query = @"<Where>
                                    <Or>
                                    <Geq>
                                        <FieldRef Name='Modified'/>
                                        <Value Type='DateTime'>" +
                                                SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Today.Date.AddDays(-1))
                                             + @"</Value>
                                    </Geq>
                                    <Geq>
                                        <FieldRef Name='Created'/>
                                        <Value Type='DateTime'>" +
                                                SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Today.Date.AddDays(-1))
                                             + @"</Value>
                                    </Geq>
                                    </Or>
                                </Where>";
                    myitems = mylist.GetItems(query);

                    if (mylist.BaseTemplate.ToString() != "WebPartCatalog"
                        && mylist.BaseTemplate.ToString() != "ListTemplateCatalog"
                        && mylist.BaseTemplate.ToString() != "MasterPageCatalog"
                        && mylist.BaseTemplate.ToString() != "WebTemplateCatalog"
                        && mylist.BaseTemplate.ToString() != "UserInformation")
                    {
                        siteList.ListTitle = mylist.Title;
                        siteList.ListURL = mylist.DefaultViewUrl;
                        siteList.TodayActivity = 0;
                        siteList.YesterdayActivity = 0;
                        DateTime createdDate, modifiedDate;

                        foreach (SPItem myitem in myitems)
                        {
                            createdDate = DateTime.Parse(myitem["Created"].ToString());
                            modifiedDate = DateTime.Parse(myitem["Modified"].ToString());

                             if ((modifiedDate.CompareTo(DateTime.Today.Date) >= 0)
                                ||
                                (createdDate.CompareTo(DateTime.Today.Date) >= 0))
                            {
                                siteList.TodayActivity += 1;
                            }
                            else if ((modifiedDate.CompareTo(DateTime.Today.Date) < 0)
                                ||
                                (createdDate.CompareTo(DateTime.Today.Date) < 0))
                            {
                                siteList.YesterdayActivity += 1;
                            }
                        }

                        siteLists.Add(siteList);
                    }

                }
                xmlString = siteLists.ToString();

                if (_webUrl != "")
                {
                    //only dispose of the myweb object if it was obtained through the site.OpenWeb() method
                    myweb.Dispose();
                }
            }
            finally
            {
                siteLists = null;

            }
            return xmlString;
        }
    }

    //TODO: implement the rest of the methods /or implement as ienumerable
    internal class SimpleListCollection : System.Collections.ArrayList
    {
        private System.Collections.ArrayList _lists;

        private string _siteTitle, _siteDescription, _webUrl;

        public string SiteTitle
        { set { _siteTitle = value; } }

        public string SiteDescription
        { set { _siteDescription = value; } }

        public string SiteUrl
        { set { _webUrl = value; } }


        public SimpleListCollection()
        {
            _lists = new System.Collections.ArrayList();
        }
        public override string ToString()
        {
            //return base.ToString();
            string listData = "";
            using (System.IO.StringWriter w = new System.IO.StringWriter())
            {
                System.Xml.XmlTextWriter xr = new XmlTextWriter(w);
                xr.WriteStartElement("Site");
                xr.WriteStartElement("SiteInfo");
                xr.WriteStartElement("SiteTitle");
                xr.WriteString(_siteTitle);
                xr.WriteEndElement();//</SiteTitle>
                xr.WriteStartElement("SiteDescription");
                xr.WriteString(_siteDescription);
                xr.WriteEndElement();//</SiteDescription>
                xr.WriteStartElement("SiteUrl");
                xr.WriteString(_webUrl);
                xr.WriteEndElement();//</SiteUrl>
                xr.WriteEndElement();//</SiteInfo>

                xr.WriteStartElement("Lists");//Lists

                foreach (SimpleList lst in _lists)
                {
                    xr.WriteStartElement("List");//List
                    xr.WriteStartElement("ListTitle");//ListTitle
                    xr.WriteString(lst.ListTitle.Trim());
                    xr.WriteEndElement();//ListTitle
                    xr.WriteStartElement("YesterdayActivity");//YA
                    xr.WriteString(lst.YesterdayActivity.ToString());
                    xr.WriteEndElement();
                    xr.WriteStartElement("TodayActivity");//TA
                    xr.WriteString(lst.TodayActivity.ToString());
                    xr.WriteEndElement();//TodayActivity
                    xr.WriteStartElement("ListUrl");//TA
                    xr.WriteString(lst.ListURL.Trim());
                    xr.WriteEndElement();//ListUrl
                    xr.WriteEndElement();//List
                }

                xr.WriteEndElement();//Lists
                xr.WriteEndElement();//Site
                listData = w.ToString();
                xr.Close();
            }

            return listData;
        }

        public override int Add(object value)
        {
            //return base.Add(value);
            return _lists.Add(value);
        }
    }
    internal class SimpleList
    {
        public SimpleList()
        {
        }

        private string _title;
        private int _yesterdayCount;
        private int _todayCount;
        private string _listUrl;

        public string ListTitle
        {
            get { return _title; }
            set { _title = value; }
        }
        public int YesterdayActivity
        {
            get { return _yesterdayCount; }
            set { _yesterdayCount = value; }
        }
        public int TodayActivity
        {
            get { return _todayCount; }
            set { _todayCount = value; }
        }
        public string ListURL
        {
            get { return _listUrl; }
            set { _listUrl = value; }
        }
    }

}
